Skip to content

SOCK_SEQPACKET UNIX Socket Fallback and Direct Shebang Execution#111

Open
doanbaotrung wants to merge 1 commit into
sysprog21:mainfrom
open-sources-port:feature/SOCK_SEQPACKET
Open

SOCK_SEQPACKET UNIX Socket Fallback and Direct Shebang Execution#111
doanbaotrung wants to merge 1 commit into
sysprog21:mainfrom
open-sources-port:feature/SOCK_SEQPACKET

Conversation

@doanbaotrung

@doanbaotrung doanbaotrung commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator
SOCK_SEQPACKET UNIX Socket Fallback

Updated sys_socket and sys_socketpair
to automatically downgrade AF_UNIX
sockets of type SOCK_SEQPACKET to
SOCK_STREAM on macOS hosts.
Initialized the socket options
cache using the original
LINUX_SOCK_SEQPACKET type,
ensuring getsockopt queries for
SO_TYPE correctly report
SOCK_SEQPACKET to the guest.

Direct Shebang Execution

Implemented a recursive shebang parsing loop
in the standalone loader's entry point.
It reads shebang interpreter lines
(including optional arguments like #!/bin/sh -x),
updates elf_path to point to the interpreter,
prepends them to guest_argv, and resolves the
host path recursively up to a depth of 5 levels.

Summary by cubic

Add a macOS-safe fallback for AF_UNIX SOCK_SEQPACKET and support direct shebang execution with recursive interpreter resolution. socket maps to SOCK_STREAM and socketpair to SOCK_DGRAM, while getsockopt(SO_TYPE) still returns SOCK_SEQPACKET.

  • New Features

    • AF_UNIX SOCK_SEQPACKET fallback: socketSOCK_STREAM, socketpairSOCK_DGRAM; cache original type so SO_TYPE reports SOCK_SEQPACKET; tests for both paths.
    • Standalone loader: resolve shebangs recursively (max 5), prepend interpreter (and one optional arg), update elf_path, clean temp files.
  • Refactors

    • Extracted elf_parse_shebang in elf.c, reused in main and sys_execve for consistent behavior.

Written for commit d6f2d70. Summary will update on new commits.

Review in cubic

@doanbaotrung doanbaotrung force-pushed the feature/SOCK_SEQPACKET branch from 66ce56b to c1e7082 Compare June 25, 2026 15:15
@doanbaotrung

Copy link
Copy Markdown
Collaborator Author

Fix #104

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found and verified against the latest diff

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/main.c
Comment thread src/main.c
Comment thread src/main.c
@doanbaotrung doanbaotrung force-pushed the feature/SOCK_SEQPACKET branch from 99a45a3 to c8288ed Compare June 25, 2026 15:43
@jserv jserv requested a review from Max042004 June 28, 2026 21:57

@Max042004 Max042004 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by the way, provide SEQPACKET test.

Comment thread src/main.c Outdated
}

/* Check if the file starts with "#!" */
FILE *f = fopen(elf_host_path, "r");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/syscall/exec.c 340~415 already have binfmt_script parsing algorithm. Consider refactoring to use shared helper function.

@doanbaotrung doanbaotrung force-pushed the feature/SOCK_SEQPACKET branch 2 times, most recently from 6bd73c7 to a051ad4 Compare July 1, 2026 02:18
@doanbaotrung

Copy link
Copy Markdown
Collaborator Author
  1. Refactor shebang parsing logic: Extract the duplicate binfmt_script parsing logic from main.c and exec.c into a shared helper function elf_parse_shebang defined in elf.c and declared in elf.h.
  2. Provide SEQPACKET test: Add test cases to test-socket.c to cover UNIX domain SOCK_SEQPACKET sockets and socketpairs, verifying that getsockopt SO_TYPE correctly returns SOCK_SEQPACKET.

Changes


[MODIFY] elf.h

  • Declare the shared helper function:
    int elf_parse_shebang(const char *host_path, char *interp_out, size_t interp_sz, char *arg_out, size_t arg_sz);

[MODIFY] elf.c

  • Implement elf_parse_shebang to:
    • Open the shebang file on the host.
    • Read the script header (up to 512 bytes).
    • Verify it starts with #!.
    • Parse the interpreter path and optional single argument, trimming leading/trailing whitespaces and carriage returns correctly.
    • Copy results to output buffers.
    • Return 1 on success, 0 if not a shebang script, or negative error code (like -ENOENT, -ENOEXEC) on failure.

[MODIFY] main.c

  • Refactor shebang resolution loop to call elf_parse_shebang and reuse its outputs.

[MODIFY] exec.c

  • Refactor fallback logic to call elf_parse_shebang and reuse its outputs.

[MODIFY] test-socket.c

  • Add Test 12: socketpair(AF_UNIX, SOCK_SEQPACKET, 0, seq_sv) to verify creation, data exchange, and getsockopt SO_TYPE returning SOCK_SEQPACKET.
  • Add Test 13: socket(AF_UNIX, SOCK_SEQPACKET, 0) to verify creation and getsockopt SO_TYPE returning SOCK_SEQPACKET.

Verification Plan

Automated Tests

  • Run the compiled test binary under elfuse to verify all tests (including the new SEQPACKET test cases) pass:
    build/elfuse build/test-socket

@doanbaotrung doanbaotrung force-pushed the feature/SOCK_SEQPACKET branch from a051ad4 to de4fb2c Compare July 1, 2026 02:21
@doanbaotrung doanbaotrung requested a review from Max042004 July 1, 2026 06:54
@Max042004

Copy link
Copy Markdown
Collaborator

sys_socket (src/syscall/net.c:97) and sys_socketpair (:174) now downgrade
every AF_UNIX SOCK_SEQPACKET request to SOCK_STREAM, while the option
cache keeps the original type (:127, :156, :210-211) so
getsockopt(SO_TYPE) still reports SOCK_SEQPACKET.

On AF_UNIX the only difference between the two types is that SEQPACKET
preserves message boundaries and STREAM does not (both are connection-oriented,
reliable, ordered). So a guest that assumes "one recv = one whole message" —
the reason to pick SEQPACKET in the first place — breaks via coalescing/short
reads, a recvmsg-until-MSG_EOR loop that never ends, or flipped small-buffer
truncation. The breakage is timing-dependent (intermittent) and, because
SO_TYPE lies, undetectable from inside the guest. Affected: systemd
ListenSequentialPacket= services, socketpair(SEQPACKET) privsep/worker
channels, any daemon using SEQPACKET for framing. Strict ping-pong users are
fine (why STREAM works for the common case). The old behavior failed cleanly at
socket() (EPROTOTYPE); this trades that for silently corrupting the
framing-dependent minority — defensible for a compat layer, but it should be a
conscious choice, and boundaries can be kept.

Two possible way to implement SEQPACKET:

  • socketpair(SEQPACKET)SOCK_DGRAM, not SOCK_STREAM (~1 line at
    net.c:174). macOS supports AF_UNIX DGRAM socketpairs; local datagrams are
    reliable, ordered, and keep message boundaries, and the pairing already
    supplies the connection semantics SEQPACKET adds over DGRAM. Fixes the most
    common pattern at zero framing cost.
  • listen/accept servers need connection semantics DGRAM lacks → SOCK_STREAM
    • userspace length-prefix framing. Larger effort; only if a real server-pattern
      guest appears.

@doanbaotrung doanbaotrung force-pushed the feature/SOCK_SEQPACKET branch from de4fb2c to 3b0b28b Compare July 1, 2026 14:15
Updated sys_socket and sys_socketpair to automatically
downgrade AF_UNIX sockets of type SOCK_SEQPACKET to
SOCK_STREAM on macOS hosts.
Initialized the socket options cache using the original
LINUX_SOCK_SEQPACKET type, ensuring getsockopt queries for
SO_TYPE correctly report SOCK_SEQPACKET to the guest.

Provide SEQPACKET test: Add test cases to test-socket.c
o cover UNIX domain SOCK_SEQPACKET sockets and socketpairs,
verifying that getsockopt SO_TYPE correctly returns SOCK_SEQPACKET.

Direct Shebang Execution

Refactor shebang parsing logic: Extract the duplicate
binfmt_script parsing logic from main.c and exec.c into
a shared helper function elf_parse_shebang defined in elf.c
and declared in elf.h.
@doanbaotrung doanbaotrung force-pushed the feature/SOCK_SEQPACKET branch from 3b0b28b to d6f2d70 Compare July 1, 2026 14:16
@doanbaotrung

Copy link
Copy Markdown
Collaborator Author

Changes Made

shebang / binfmt_script Refactoring

  • elf.h: Declared the helper function elf_parse_shebang to parse script files starting with a shebang (#!).
  • elf.c: Implemented elf_parse_shebang using safe buffer/string utilities (str_copy_trunc) to avoid security violations (such as strcpy).
  • main.c: Replaced duplicate shebang parsing logic with a call to elf_parse_shebang.
  • exec.c: Replaced duplicate shebang parsing logic with a call to elf_parse_shebang.

SOCK_SEQPACKET Emulation & Boundary Preservation Tests

  • net.c: Updated sys_socketpair to downgrade UNIX domain SOCK_SEQPACKET socketpairs to SOCK_DGRAM instead of SOCK_STREAM. Since macOS fully supports AF_UNIX datagram socketpairs (which are reliable, ordered, and preserve message boundaries), this preserves sequential packet connection semantics at zero framing cost.
  • test-socket.c: Added/enhanced the test cases:
    • Test 12: Verifies creation of UNIX domain SOCK_SEQPACKET socketpair using consecutive writes, checking that reading from the socketpair preserves message boundaries (returns distinct messages and sizes instead of coalescing/short reads) and that getsockopt SO_TYPE correctly returns SOCK_SEQPACKET.
    • Test 13: Verifies creation of UNIX domain SOCK_SEQPACKET socket, and ensures getsockopt SO_TYPE correctly returns SOCK_SEQPACKET.

Verification & Testing

Security Check

All security checks passed:

bash .ci/check-security.sh
# Output: Security checks passed.

Compilation

  1. Compiled the refactored elfuse binary natively on macOS:
    make elfuse

Execution Results

Executed test-socket under elfuse showing that both the standard tests and the updated SOCK_SEQPACKET boundary tests pass cleanly:

test-socket: 1. socketpair(AF_UNIX)... PASS (fds=3,4)
test-socket: 2. write/read through socketpair... PASS
test-socket: 3. getsockopt(SO_TYPE)... PASS
test-socket: 4. getsockname/getpeername... PASS
test-socket: 5. sendmsg/recvmsg single iovec... PASS
test-socket: 6. sendmsg/recvmsg two iovecs... PASS
test-socket: 7. sendmmsg/recvmmsg single message... PASS
test-socket: 8. sendto/recvfrom AF_UNIX dgram... PASS
test-socket: 9. recvmsg single iovec preserves MSG_TRUNC... PASS
test-socket: 10. getsockopt(SO_ERROR) read-and-clear... PASS
test-socket: 11. shutdown(SHUT_WR) -> EOF... PASS
test-socket: 12. socketpair(AF_UNIX, SOCK_SEQPACKET)... PASS
test-socket: 13. socket(AF_UNIX, SOCK_SEQPACKET)... PASS
test-socket: all tests passed -- PASS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants